/*
 * An I2C driver for the Philips PCF8563 RTC
 * Copyright 2005-06 Tower Technologies
 *
 * Author: Alessandro Zummo <a.zummo@towertech.it>
 * Maintainers: http://www.nslu2-linux.org/
 *
 * based on the other drivers in this same directory.
 *
 * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/i2c.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/slab.h>
static void gpio_keys_work_func(struct work_struct *work);
#define DRV_VERSION "0.4.3"

#define PCF8563_REG_ST1     0x00 /* status */
#define PCF8563_REG_ST2     0x01

#define PCF8563_REG_SC      0x02 /* datetime */
#define PCF8563_REG_MN      0x03
#define PCF8563_REG_HR      0x04
#define PCF8563_REG_DM      0x05
#define PCF8563_REG_DW      0x06
#define PCF8563_REG_MO      0x07
#define PCF8563_REG_YR      0x08

#define PCF8563_REG_AMN     0x09 /* alarm */
#define PCF8563_REG_AHR     0x0A
#define PCF8563_REG_ADM     0x0B
#define PCF8563_REG_ADW     0x0C

#define PCF8563_REG_CLKO    0x0D /* clock out */
#define PCF8563_REG_TMRC    0x0E /* timer control */
#define PCF8563_REG_TMR     0x0F /* timer */

#define PCF8563_SC_LV       0x80 /* low voltage */
#define PCF8563_MO_C        0x80 /* century */

#include <mach/pinctrl.h>
#include <linux/input.h>
#include <linux/hrtimer.h>
#include <linux/kthread.h> 
#include <linux/delay.h> 
static unsigned char *wr_buf;
struct input_dev *input_dev;

// struct workqueue_struct *p_queue;
// struct timer_list timer;
struct hrtimer watchdog;
struct work_struct work;
struct task_struct * my_thread = NULL;

struct completion continue_report;
struct completion thread_run;

int gpio_irq = MXS_PIN_TO_GPIO(MXS_PIN_ENCODE(0, 18));
// int gpio_irq = MXS_PIN_TO_GPIO(MXS_PIN_ENCODE(2, 5));

static struct i2c_driver s7611_driver;

struct s7611_data {
    struct rtc_device *rtc;
    struct timer_list timer;
    struct work_struct work;
    struct i2c_client *client;
    /*
     * The meaning of MO_C bit varies by the chip type.
     * From PCF8563 datasheet: this bit is toggled when the years
     * register overflows from 99 to 00
     *   0 indicates the century is 20xx
     *   1 indicates the century is 19xx
     * From RTC8564 datasheet: this bit indicates change of
     * century. When the year digit data overflows from 99 to 00,
     * this bit is set. By presetting it to 0 while still in the
     * 20th century, it will be set in year 2000, ...
     * There seems no reliable way to know how the system use this
     * bit.  So let's do it heuristically, assuming we are live in
     * 1970...2069.
     */
    int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
};

/*
 * In the routines that deal directly with the pcf8563 hardware, we use
 * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
 */
static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
{
    struct s7611_data *pcf8563 = i2c_get_clientdata(client);
    unsigned char buf[13] = { PCF8563_REG_ST1 };

    struct i2c_msg msg[] = {
        { client->addr, 0, 1, buf },    /* setup read ptr */
        { client->addr, I2C_M_RD, 13, buf },    /* read status + date */
    };

    /* read registers */
    if ((i2c_transfer(client->adapter, msg, 2)) != 2) {
        dev_err(&client->dev, "%s: read error\n", __func__);
        return -EIO;
    }

    if (buf[PCF8563_REG_SC] & PCF8563_SC_LV)
        dev_info(&client->dev,
                 "low voltage detected, date/time is not reliable.\n");

    dev_dbg(&client->dev,
            "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
            "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
            __func__,
            buf[0], buf[1], buf[2], buf[3],
            buf[4], buf[5], buf[6], buf[7],
            buf[8]);


    tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
    tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
    tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
    tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
    tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
    tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
    tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
    if (tm->tm_year < 70) {
        tm->tm_year += 100;    /* assume we are in 1970...2069 */
    }
    /* detect the polarity heuristically. see note above. */
    pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
                          (tm->tm_year >= 100) : (tm->tm_year < 100);

    dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
            "mday=%d, mon=%d, year=%d, wday=%d\n",
            __func__,
            tm->tm_sec, tm->tm_min, tm->tm_hour,
            tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

    /* the clock can give out invalid datetime, but we cannot return
     * -EINVAL otherwise hwclock will refuse to set the time on bootup.
     */
    if (rtc_valid_tm(tm) < 0) {
        dev_err(&client->dev, "retrieved date/time is not valid.\n");
    }

    return 0;
}

static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
    struct s7611_data *pcf8563 = i2c_get_clientdata(client);
    int i, err;
    unsigned char buf[9];

    dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
            "mday=%d, mon=%d, year=%d, wday=%d\n",
            __func__,
            tm->tm_sec, tm->tm_min, tm->tm_hour,
            tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);

    /* hours, minutes and seconds */
    buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
    buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
    buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);

    buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);

    /* month, 1 - 12 */
    buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);

    /* year and century */
    buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
    if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)) {
        buf[PCF8563_REG_MO] |= PCF8563_MO_C;
    }

    buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;

    /* write register's data */
    for (i = 0; i < 7; i++) {
        unsigned char data[2] = { PCF8563_REG_SC + i,
                                  buf[PCF8563_REG_SC + i]
                                };

        err = i2c_master_send(client, data, sizeof(data));
        if (err != sizeof(data)) {
            dev_err(&client->dev,
                    "%s: err=%d addr=%02x, data=%02x\n",
                    __func__, err, data[0], data[1]);
            return -EIO;
        }
    };

    return 0;
}

struct s7611_data_limit {
    unsigned char reg;
    unsigned char mask;
    unsigned char min;
    unsigned char max;
};

static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
    return pcf8563_get_datetime(to_i2c_client(dev), tm);
}

static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
    return pcf8563_set_datetime(to_i2c_client(dev), tm);
}

static const struct rtc_class_ops pcf8563_rtc_ops = {
    .read_time  = pcf8563_rtc_read_time,
    .set_time   = pcf8563_rtc_set_time,
};


extern struct i2c_client *g_i2c;

static ssize_t timeout_show(struct device *dev,
                            struct device_attribute *attr, char *buf)
{

    return sprintf(buf, "%u\n", 13);
}

static struct device_attribute glink_class_attrs[] = {
    __ATTR(timeout, 0644, timeout_show, NULL),
};
static struct class *glink_class;
struct f08_2d_data {
    char type;
    short x;
    short y;
    char z;
    short w;
} __attribute__ ((__packed__));

static int touch_report(struct i2c_client *client1, char addr);
static int read_finger(struct i2c_client *client1, char addr);
static int _2byte_addr(struct i2c_client *client1, char page, char addr_in_page);
static int w_2byte_addr(struct i2c_client *client1, char page, char addr_in_page,
                        char *data, int len);

static int test(struct i2c_client *client1, char addr);
static int synaptics_rmi4_i2c_set_page(struct i2c_client *client1, short addr)
{
    unsigned char tbuf[2];
    unsigned char rbuf[20];

    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    // client = client1;
    printk("client1 %x g_i2c %x\r\n", client1, g_i2c);
    int k = 0, i;
    struct i2c_msg msg[1];
    msg[0].addr = 0x20;
    msg[0].flags = 0;
    msg[0].len = 2;
    msg[0].buf = tbuf;

    tbuf[0] = 0xff;
    tbuf[1] = (addr & 0xff00) >> 8;

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: set page error\n", __func__);
        return -EIO;
    }
}

static int synaptics_rmi4_i2c_read(struct i2c_client *client1,
                                   unsigned short addr, unsigned char *data, unsigned short length, 
                                   int print)
{
    unsigned char tbuf[2];
    unsigned char rbuf[20];
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    struct i2c_msg msg[2];
    client = g_i2c;
    int k = 0, i;

    synaptics_rmi4_i2c_set_page(NULL, addr);


    msg[0].addr = 0x20;
    msg[0].flags = 0;
    msg[0].len = 1;
    msg[0].buf = tbuf;

    msg[1].addr = 0x20;
    msg[1].flags = I2C_M_RD;
    msg[1].len = length;
    msg[1].buf = data;

    tbuf[0] = addr & 0x00ff;

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: read page error\n", __func__);
        return -EIO;
    }

    if (print) {
        for (i = 0; i < length; i++) {
            printk("%2.2x ", data[i]);
        }
        printk("\r\n");
    }
}

static int synaptics_rmi4_i2c_write(struct i2c_client *client1,
                                    unsigned short addr, unsigned char *data, unsigned short length)
{
    unsigned char tbuf[10];
    unsigned char rbuf[20];
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    struct i2c_msg msg[1];
    // printk("g_i2c not NULL\r\n");
    client = g_i2c;
    int k = 0, i;

    synaptics_rmi4_i2c_set_page(NULL, addr);

    msg[0].addr = 0x20;
    msg[0].flags = 0;
    msg[0].len = length + 1;
    msg[0].buf = wr_buf;
    wr_buf[0] = addr & 0x00ff;

    // msg[1].addr = 0x20;
    // msg[1].flags = 0;
    // msg[1].len = 5;
    // msg[1].buf = tbuf;

    memcpy(wr_buf + 1, data, 5);
    // printk("[%x %x %x]\r\n", tbuf[0], tbuf[1], tbuf[2]);

    // tbuf[0] = addr & 0x00ff;
    // tbuf[1] = 0xa1;
    // tbuf[2] = 0xa2;
    // tbuf[3] = 0xa3;
    // tbuf[4] = 0xa4;
    // tbuf[5] = 0xa1;

    // msg[1].addr = 0x20;
    // msg[1].flags = 0;
    // msg[1].len = length;
    // msg[1].buf = data;


    int count = sizeof(msg) / sizeof(struct i2c_msg);
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: read page error\n", __func__);
        return -EIO;
    }

    // for (i = 0;i < length; i++) {
    //  printk("%2.2x ", data[i]);
    // }
    // printk("\r\n");
}

static int test(struct i2c_client *client1, char addr)
{

    // struct s7611_data *pcf8563 = i2c_get_clientdata(client1);
    // unsigned char tbuf[4] = { 0x06,0x06 };
    unsigned char tbuf[4] = { addr };
    unsigned char rbuf[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    struct i2c_client *client;

    // synaptics_rmi4_i2c_set_page(NULL, addr);
    synaptics_rmi4_i2c_read(NULL, addr, rbuf, sizeof(rbuf), 1);
    return 0;

    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    int k = 0;
    // for (k = 0;k < 4;k++) {
    // tbuf[0] = 0xff;
    // tbuf[1] = addr;
    tbuf[0] = addr;
    // tbuf[0] = 0xff;
    // tbuf[1] = 0x01;
    struct i2c_msg msg[] = {
        { 0x20, 0, 1, tbuf },   /* setup read ptr */
        // { 0x20, 0, 1, tbuf },    /* setup read ptr */
        { 0x20, I2C_M_RD, sizeof(rbuf), rbuf }, /* read status + date */
    };

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    /* read registers */
    i2c_transfer(client->adapter, &msg[0], 1);
    i2c_transfer(client->adapter, &msg[1], 1);
    // if ((i2c_transfer(client->adapter, msg, count)) != count) {
    //  dev_err(&client->dev, "%s: read error\n", __func__);
    //  return -EIO;
    // }
    int i;
    printk("page 0x%2.2x(%d)\r\n", addr, addr);
    for (i = 0; i < sizeof(rbuf); i++) {
        printk("%2.2x ", rbuf[i]);
    }
    printk("\r\n");
    addr++;
    // }
    read_finger(client1, addr);
    // _2byte_addr(client1, addr, 0);
    // w_2byte_addr(client1, addr, 0, NULL, NULL);

}
// static struct class *glink_class;
// struct f08_2d_data
// {
//  char type;
//  short x;
//  short y;
//  char z;
//  short w;
// };
static int touch_report(struct i2c_client *client1, char addr)
{
    int i;
    unsigned char rbuf[sizeof(struct f08_2d_data) * 5] = {0};
    // synaptics_rmi4_i2c_set_page(NULL, 0x0008);
    synaptics_rmi4_i2c_read(NULL, 0x0008, rbuf, sizeof(rbuf), 0);
    
    struct f08_2d_data *pdata =  (struct f08_2d_data *)rbuf;
    static int deta = 1;
    if (pdata->type) {
        input_report_abs(input_dev, ABS_X, pdata->x + deta);
        input_report_abs(input_dev, ABS_Y, pdata->y + deta); 
        input_report_abs(input_dev, ABS_PRESSURE, pdata->type);
        // continue_report = 1;
        complete(&continue_report);
        deta = deta * -1;
    }
    else {
        input_report_abs(input_dev, ABS_PRESSURE, pdata->type);
        // continue_report = 0;
    }
    input_sync(input_dev);
    // printk("type\tX\tY\tz\tW\r\n");
    // for (i = 0; i < 5; i++) {
    //  printk("%d\t%d\t%d\t%d\t%d\t\r\n", pdata->type, pdata->x, pdata->y, pdata->z, pdata->w);
    //  pdata++;

    // }
}
static int read_finger(struct i2c_client *client1, char addr)
{
    // struct s7611_data *pcf8563 = i2c_get_clientdata(client1);
    // unsigned char tbuf[4] = { 0x06,0x06 };
    unsigned char tbuf[4] = { addr };
    unsigned char rbuf[sizeof(struct f08_2d_data) * 5] = {0};
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    int k = 0;


    // synaptics_rmi4_i2c_set_page(NULL, 0x0008);
    synaptics_rmi4_i2c_read(NULL, 0x0008, rbuf, sizeof(rbuf), 0);


    rbuf[0] = 0x00;
    rbuf[1] = 0x00;
    rbuf[2] = 0x00;
    rbuf[3] = 0x00;
    rbuf[4] = 0x00;
    rbuf[5] = 0x00;
    rbuf[6] = 0x00;
    rbuf[7] = 0x00;
    synaptics_rmi4_i2c_write(NULL, 0x0012, rbuf, 7);

    // synaptics_rmi4_i2c_set_page(NULL, 0x0012);
    synaptics_rmi4_i2c_read(NULL, 0x0012, rbuf, sizeof(rbuf), 0);

    int i;

    struct f08_2d_data *pdata =  (struct f08_2d_data *)rbuf;
    printk("type\tX\tY\tz\tW\r\n");
    for (i = 0; i < 5; i++) {
        printk("%d\t%d\t%d\t%d\t%d\t\r\n", pdata->type, pdata->x, pdata->y, pdata->z, pdata->w);
        pdata++;

    }
}

static int _2byte_addr(struct i2c_client *client1, char page, char addr_in_page)
{
    // struct s7611_data *pcf8563 = i2c_get_clientdata(client1);
    // unsigned char tbuf[4] = { 0x06,0x06 };
    unsigned char tbuf[4] = { page };
    unsigned char rbuf[20] = {0};
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    int k = 0;

    tbuf[0] = page;
    tbuf[1] = addr_in_page;
    struct i2c_msg msg[] = {
        { 0x20, 0, 2, tbuf },   /* setup read ptr */
        // { 0x20, 0, 1, tbuf },    /* setup read ptr */
        { 0x20, I2C_M_RD, sizeof(rbuf), rbuf }, /* read status + date */
    };

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    /* read registers */
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: read error\n", __func__);
        return -EIO;
    }
    int i;
    printk("page 0x%2.2x(%d)\r\n", page, addr_in_page);
    for (i = 0; i < sizeof(rbuf); i++) {
        printk("%2.2x ", rbuf[i]);
    }
    printk("\r\n");
}
static int w_2byte_addr(struct i2c_client *client1, char page, char addr_in_page,
                        char *data, int len)
{
    unsigned char tbuf[4] = { page };
    // page 2
    // 18 05 14 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    unsigned char rbuf[20] = {0x1f, 0x1f, 0x14, 0x1f, 0x1f};
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    int k = 0;

    tbuf[0] = page;
    tbuf[1] = addr_in_page;
    struct i2c_msg msg[] = {
        { 0x20, 0, 2, tbuf },   /* setup read ptr */
        // { 0x20, 0, 1, tbuf },    /* setup read ptr */
        { 0x20, 0, len, rbuf }, /* read status + date */
    };

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    /* read registers */
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: read error\n", __func__);
        return -EIO;
    }
    int i;

}

static int _enable_irq(struct i2c_client *client1)
{
    // unsigned char tbuf[4];
    // // page 2
    // // 18 05 14 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    // unsigned char rbuf[20] = {0x1f, 0x1f,0x14, 0x1f,0x1f};
    // struct i2c_client *client;
    // if (g_i2c == NULL) {
    //  return -1;
    // }
    // client = g_i2c;
    // int k = 0;

    // tbuf[0] = 0x02;
    // tbuf[1] = 0x00;
    // struct i2c_msg msg[] = {
    //  { 0x20, 0, 2, tbuf },
    //  // { 0x20, 0, 1, tbuf },
    //  { 0x20, 0, 5, rbuf },
    // };

    // int count = sizeof(msg)/sizeof(struct i2c_msg);
    // /* read registers */
    // if ((i2c_transfer(client->adapter, msg, count)) != count) {
    //  dev_err(&client->dev, "%s: read error\n", __func__);
    //  return -EIO;
    // }
    // printk("lllll\r\n");

    unsigned char tbuf[4];
    // page 2
    // 18 05 14 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    unsigned char rbuf[20] = {0x1f, 0x1f, 0x14, 0x1f, 0x1f};
    struct i2c_client *client;
    if (g_i2c == NULL) {
        return -1;
    }
    client = g_i2c;
    int k = 0;

    tbuf[0] = 0x07;
    struct i2c_msg msg[] = {
        { 0x20, 0, 1, tbuf },   /* setup read ptr */
        // { 0x20, 0, 1, tbuf },    /* setup read ptr */
        { 0x20, I2C_M_RD, 1, rbuf },    /* read status + date */
    };

    int count = sizeof(msg) / sizeof(struct i2c_msg);
    /* read registers */
    if ((i2c_transfer(client->adapter, msg, count)) != count) {
        dev_err(&client->dev, "%s: read error\n", __func__);
        return -EIO;
    }
    printk("lllll\r\n");

}
// 读取按各手指坐标

// static int __init pcf8563_init(void)
// {
//  printk("%s() %d\n", __FUNCTION__, __LINE__);
//  glink_class = class_create(THIS_MODULE, "glink");
//  if (IS_ERR(glink_class))
//      return PTR_ERR(glink_class);
//  printk("%s() %d\n", __FUNCTION__, __LINE__);
//  glink_class->dev_attrs = glink_class_attrs;

//  test(NULL, NULL);

//  return i2c_add_driver(&s7611_driver);
//  return 0;
// }

// static void __exit pcf8563_exit(void)
// {
//  i2c_del_driver(&s7611_driver);
//  return 0;
// }


#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>




#define CNT_BATTERY (1)

struct vol_2_per {
    int voltage;
    int percent;
};

struct misc_batt_data {
    char name[16];
    int voltage;
    int status;
    int percent;
    struct vol_2_per *v2p_table;
};


static ssize_t name_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;

    return snprintf(buf, PAGE_SIZE, "%s\n", pdata->name);
}

static ssize_t battery_voltage_show(
    struct device *dev,
    struct device_attribute *attr,
    char *buf)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;
    int i;
    // for (i = 0;i < 4;i++) {
    test(NULL, NULL);
    // }
    return snprintf(buf, PAGE_SIZE, "%d\n", pdata->voltage);
}
static ssize_t battery_voltage_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;
    char *after;

    pdata->voltage = simple_strtoul(buf, &after, 16);
    // printk("after [%d] [%s]\r\n", pdata->voltage);
    test(NULL, pdata->voltage);
    // pdata->voltage = simple_strtoul(buf, &after, 10);
    return count;
}



static ssize_t enable_irq_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;
    char *after;

    _enable_irq(g_i2c);
    return count;
}
static ssize_t mutil_finger_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;
    char *after;


    read_finger(g_i2c, 0x08);
    return count;
}

static ssize_t _2addr_write_store(
    struct device *dev,
    struct device_attribute *attr,
    const char *buf,
    size_t count)
{
    struct misc_batt_data *pdata = (struct misc_batt_data *)dev->platform_data;
    char *after;
    short addr;
    char value;
    addr = simple_strtoul(buf, &after, 16);
    value = simple_strtoul(buf + 5, &after, 16);

    w_2byte_addr(g_i2c, (addr & 0xff00) >> 8, addr & 0x00ff, value, 1);
    return count;
}

static DEVICE_ATTR(
    name, S_IRUGO, name_show, NULL);
static DEVICE_ATTR(
    read_page, S_IWUSR | S_IRUGO, battery_voltage_show, battery_voltage_store);
// static DEVICE_ATTR(
//     percent, S_IRUGO, battery_percent_show, NULL);
// static DEVICE_ATTR(
//     status, S_IWUSR | S_IRUGO, battery_status_show, battery_status_store);
static DEVICE_ATTR(
    enable_irq, S_IWUSR | S_IRUGO, NULL, enable_irq_store);
static DEVICE_ATTR(
    mutil_finger, S_IWUSR | S_IRUGO, NULL, mutil_finger_store);

static DEVICE_ATTR(
    _2addr_write, S_IWUSR | S_IRUGO, NULL, _2addr_write_store);
static struct miscdevice *pmisc;




int success_irq = 0;
static void gpio_keys_timer(unsigned long _data)
{
    unsigned char rbuf[1] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    printk("timer\r\n");
    // synaptics_rmi4_i2c_read(NULL, 0x0007, rbuf, sizeof(rbuf), 0);
    // test(NULL, 7);
    touch_report(NULL, NULL);
    printk("timer finish\r\n");
    synaptics_rmi4_i2c_read(NULL, 0x0007, rbuf, 1, 0);
    
    enable_irq(gpio_to_irq(gpio_irq));
    
}
static void gpio_keys_work_func(struct work_struct *work)
{
    // printk("work\r\n");
    // struct s7611_data *bdata =
    //     container_of(work, struct s7611_data, work);
    unsigned char rbuf[1] = {0};
    struct i2c_client *client;

    touch_report(NULL, NULL);
    // synaptics_rmi4_i2c_read(&bdata->client, 0x0007, rbuf, 1, 0);
    synaptics_rmi4_i2c_read(NULL, 0x0007, rbuf, 1, 0);

    enable_irq(gpio_to_irq(gpio_irq));
}
static irqreturn_t s7611_ts_interrupt(int irq, void *dev_id)
{
    struct s7611_data *bdata = dev_id;
    
    disable_irq_nosync(gpio_to_irq(gpio_irq));
    printk("in irq --------\r\n");
    if (success_irq) {
        printk("irq schedule_work\r\n");
        // 准备好了能调用，不加判断会崩溃
        // schedule_work(&bdata->work);
        schedule_work(&work);
    }
    return IRQ_HANDLED;
}
int thread_detect_touch_keep_down(void *arg)
{   // 等待exit调用kthread_stop
    while(!kthread_should_stop()) {
        msleep(10);
        // 等待 complete 被调用，
        if (wait_for_completion_timeout(&continue_report, msecs_to_jiffies(1000))) {
            touch_report(NULL, NULL);   
        }
    }
    complete(&thread_run);  
    return 0;
}

static int s7611_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
{
    struct s7611_data *s7611;

    int err = 0;

    // printk(&client->dev, "%s\n", __func__);
    printk("kkkkkkkkkkkkkkkkkk\r\n");

    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
        return -ENODEV;

    s7611 = kzalloc(sizeof(struct s7611_data), GFP_KERNEL);
    if (!s7611)
        return -ENOMEM;

    dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");

    i2c_set_clientdata(client, s7611);
    // INIT_WORK(&s7611->work, gpio_keys_work_func);
    // s7611->rtc = rtc_device_register(s7611_driver.driver.name,
    //          &client->dev, &pcf8563_rtc_ops, THIS_MODULE);

    // if (IS_ERR(pcf8563->rtc)) {
    //  err = PTR_ERR(pcf8563->rtc);
    //  goto exit_kfree;
    // }



    int irq = gpio_to_irq(gpio_irq);
    printk("irq %d\r\n", irq);
    // p_queue=create_workqueue("my_queue");
    
    // hrtimer_init(&watchdog, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    // watchdog.function = test_get_report_timeout;
    
    init_completion(&continue_report);
    init_completion(&thread_run);
    
    my_thread = kthread_run(thread_detect_touch_keep_down, NULL, "s7611d");
    // if (IS_ERR(my_thread)) 
    // {
    //     rc = PTR_ERR(my_thread);
    //     printk("error %d create thread_name thread");
    // }
    
    setup_timer(&s7611->timer, gpio_keys_timer, NULL);
    // INIT_WORK(&s7611->work, gpio_keys_work_func);
    INIT_WORK(&work, gpio_keys_work_func);
    printk("line %d\r\n", __LINE__);
    int rbuf[1];
    
    err = request_irq(irq, s7611_ts_interrupt,
                      IRQF_TRIGGER_FALLING , "s7611", s7611);
    printk("line %d\r\n", __LINE__);
    if (err < 0) {
        printk("fail\r\n");
        return 0;
    }
    
    synaptics_rmi4_i2c_read(NULL, 0x0007, rbuf, 1, 0);
    success_irq = 1;
    printk("line %d\r\n", __LINE__);
    printk("line %d\r\n", __LINE__);
    return 0;

exit_kfree:
    kfree(s7611);

    return err;
}

static int s7611_remove(struct i2c_client *client)
{
    struct s7611_data *s7611 = i2c_get_clientdata(client);
    if (success_irq) {
        free_irq(gpio_to_irq(gpio_irq), s7611);
    }
    // if (pcf8563->rtc) {
    //  rtc_device_unregister(pcf8563->rtc);
    // }

    kfree(s7611);

    return 0;
}

static const struct i2c_device_id s7611_id[] = {
    { "s7611", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, s7611_id);

static struct i2c_driver s7611_driver = {
    .driver     = {
        .name   = "s7611",
    },
    .probe      = s7611_probe,
    .remove     = s7611_remove,
    .id_table   = s7611_id,
};

int __init battery_init(void)
{
    int                    i, err;
    char                   name[16];
    struct device         *this_dev;
    struct miscdevice     *tpmisc;
    struct misc_batt_data *pdata, *tpdata;

    i2c_add_driver(&s7611_driver);
    pmisc = kzalloc(sizeof(struct miscdevice) * CNT_BATTERY, GFP_KERNEL);
    pdata = kzalloc(sizeof(struct misc_batt_data) * CNT_BATTERY, GFP_KERNEL);
    wr_buf = kzalloc(256, GFP_KERNEL);

    input_dev = input_allocate_device();
    if (!input_dev) {
        printk("failed to allocate input device\n");
    }

    // ts->input_dev = input_dev;

    set_bit(EV_SYN, input_dev->evbit);
    set_bit(EV_ABS, input_dev->evbit);
    set_bit(EV_KEY, input_dev->evbit);

#ifdef CONFIG_FT5X0X_MULTITOUCH
    set_bit(ABS_MT_TRACKING_ID, input_dev->absbit);
    set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
    set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
    set_bit(ABS_MT_POSITION_X, input_dev->absbit);
    set_bit(ABS_MT_POSITION_Y, input_dev->absbit);

    input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 2048, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 1024, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 2000, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
    input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 1000, 0, 0);
#else
    set_bit(ABS_X, input_dev->absbit);
    set_bit(ABS_Y, input_dev->absbit);
    set_bit(ABS_PRESSURE, input_dev->absbit);
    set_bit(BTN_TOUCH, input_dev->keybit);

    input_set_abs_params(input_dev, ABS_X, 0, 1000, 0, 0);
    input_set_abs_params(input_dev, ABS_Y, 0, 1024, 0, 0);
    input_set_abs_params(input_dev, ABS_PRESSURE, 0, 2000, 0 , 0);
#endif
    input_dev->name = "s7611-ts";

    err = input_register_device(input_dev);
    if (err) {
        input_free_device(input_dev);
        printk("failed to register input device %d\n", err);
        // goto exit_input_dev_alloc_failed;
    }

    tpmisc = pmisc, tpdata = pdata;
    for (i = 0; i < CNT_BATTERY; i++) {
        snprintf(name, sizeof(name), "battery%d", i);
        tpmisc->name  = name;
        tpmisc->minor = MISC_DYNAMIC_MINOR;
        tpmisc->fops  = NULL;
        misc_register(tpmisc);

        this_dev                = tpmisc->this_device;
        this_dev->platform_data = tpdata;

        tpdata->voltage         = 8055;     /* 默认8000mV */
        tpdata->status          = 0;        /* 没插入适配器 */
        tpdata->percent         = 100;      /* 100%电量 */

        strncpy(tpdata->name, name, sizeof(((struct misc_batt_data *)(0))->name));

        // device_create_file(this_dev, &dev_attr_name);
        device_create_file(this_dev, &dev_attr_read_page);
        device_create_file(this_dev, &dev_attr__2addr_write);
        // device_create_file(this_dev, &dev_attr__1addr_write);
        // device_create_file(this_dev, &dev_attr_percent);
        // device_create_file(this_dev, &dev_attr_status);
        device_create_file(this_dev, &dev_attr_enable_irq);
        device_create_file(this_dev, &dev_attr_mutil_finger);
        tpmisc++, tpdata++;


    }
    ;

    
    return 0;
}

void __exit battery_exit(void)
{
    int i;
    struct miscdevice *tpmisc;
    
    i2c_del_driver(&s7611_driver);
    
    kthread_stop(my_thread);
    // if (success_irq) {
    //  free_irq(gpio_to_irq(gpio_irq), NULL);
    // }
    if (input_dev) {
        input_unregister_device(input_dev);
        input_free_device(input_dev);
        
    }
    
    if (pmisc) {
        tpmisc = pmisc;
        for (i = 0; i < CNT_BATTERY; i++) {
            misc_deregister(tpmisc);
            tpmisc++;
        }
        kfree(pmisc);
    }
}

MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);

module_init(battery_init);
module_exit(battery_exit);
